package cn.iocoder.yudao.module.system.controller.app.wechat;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.system.util.CheckoutUtil;
import cn.iocoder.yudao.module.system.util.PushMessage;
import cn.iocoder.yudao.module.system.util.XmlUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "微信公众号事件推送")
@RestController
@RequestMapping("/system/wechatEvent")
@Slf4j
public class WeChatEventController {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * key 前缀
     */
    private static final String key_prefix = "wechatCallback";

    /**
     * ReentrantLock
     */
    static Lock lock = new ReentrantLock();

    /**
     * 第一次服务器的验证
     *
     * @param signature signature
     * @param timestamp timestamp
     * @param nonce     nonce
     * @param echostr   echostr
     * @param response  response
     * @throws ServletException ServletException
     * @throws IOException      IOException
     */
    @GetMapping("/checkWechat")
    public void wechatCallbackApi(@RequestParam("signature") String
                                          signature,
                                  @RequestParam("timestamp") String timestamp,
                                  @RequestParam("nonce") String nonce,
                                  @RequestParam("echostr") String echostr, HttpServletResponse response)
            throws ServletException, IOException {
        log.info("[服务器配置],进入是数据signature{},timestamp{},nonce{},echostr{}", signature, timestamp, nonce, echostr);
        PrintWriter print;
        // 通过检验signature对请求进行校验，若校验成功则原样返回echostr，表示接入成功，否则接入失败
        if (signature != null && CheckoutUtil.checkSignature(signature,
                timestamp, nonce)) {
            log.info("[服务器配置],验证通过", "success");
            try {
                print = response.getWriter();
                print.write(echostr);
                print.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 礼品卡事件推送
     *
     * @param notifyData
     * @throws ServletException
     * @throws IOException
     */
    @PostMapping("/checkWechat")
    public void wechatCallbackApi(@RequestBody String notifyData) throws ServletException, IOException {
        lock.lock();
        try {
            log.info("[服务器配置],进入事件通知{}", notifyData);
            PushMessage message = (PushMessage) XmlUtil.fromXML(notifyData, PushMessage.class);
            Objects.requireNonNull(message, "[微信信息事件通知]，返回为空！");
            //去重 重复消息
            String msgId = key_prefix + message.getFromUserName() + message.getCreateTime() + message.getEvent();
            boolean hasMsgId = stringRedisTemplate.hasKey(msgId);
            if (!hasMsgId) {
                //保留一天 用于查询
                stringRedisTemplate.opsForValue().set(msgId, message.toString(), Duration.ofSeconds(60 * 60 * 24));
                log.info("[服务器配置],进入事件通知转对象信息结果{}", message);
                String event = message.getEvent();
                log.info("[服务器配置],事件类型{}", event);

                // TODO: 2024/1/12 待处理
                if ("giftcard_pay_done".equals(event)) {
                    //用户购买礼品卡付款成功CallBack

                } else if ("giftcard_send_to_friend".equals(event)) {
                    //用户购买后赠送CallBack

                } else if ("giftcard_user_accept".equals(event)) {
                    //用户领取礼品卡成功CallBack

                } else if ("user_get_card".equals(event)) {
                    //赠送24小时对方未领取退回后的事件 领取协议

                } else if ("user_gifting_card".equals(event)) {
                    //赠送24小时对方未领取退回后的事件 转赠协议

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    @GetMapping("/queryRedisHistoryMessage")
    @Operation(summary = "获取消息缓存历史信息")
    public CommonResult<List> queryRedisHistoryMessage() {
        Set<String> keys = stringRedisTemplate.keys(key_prefix + "*");
        List historyMessage = new ArrayList();
        if (null != keys) {
            historyMessage = stringRedisTemplate.opsForValue().multiGet(keys);
        }
        return success(historyMessage);
    }

}
